Skip to content

feat(ui): message inspector + session panel#38

Merged
sepehr-safari merged 1 commit into
mainfrom
feat/message-inspector
Jul 11, 2026
Merged

feat(ui): message inspector + session panel#38
sepehr-safari merged 1 commit into
mainfrom
feat/message-inspector

Conversation

@sepehr-safari

Copy link
Copy Markdown
Member

Summary

Turns the detail pane into a real message inspector. Selecting a timeline row
(#28) now unpacks the event completely and shows the session it belongs to.

  • Normalized fields — id, message id, type, direction, timestamp, and the
    error code/description for CallError.
  • Session panel — the session the event correlates into: transaction id,
    status (colored), connector, start/stop, and event count, plus a
    Jump to first event control.
  • Payload tree — a model-owned disclosure tree over the std.json.Value
    payload (ui.tree + the ARIA keymap: Up/Down roving focus, Left collapses,
    Right expands, Enter selects). Objects/arrays expand; scalars are leaves
    (strings quoted).
  • Raw message — the original OCPP-J array, pretty-printed.

Design notes

  • Flat treeitem rows. The tree is a flat, pre-order list of role=.treeitem
    rows with depth encoded as indentation, not physically nested containers. The
    per-row keymap resolves off each row's own expanded state and roving focus
    walks document order, so flatness keeps the full ARIA keymap while cutting each
    row to ~4 widget nodes — the timeline is windowed, but the detail tree is not,
    so node cost matters.
  • Collapse-independent ids. Each node's collapse bit is keyed by its
    pre-order rank over the bounded payload. The walk always advances the id
    counter over every in-bounds node (emitting a row only when visible), so a
    collapse bit always names the same node across rebuilds — toggling one node
    never shifts another's identity. State is a fixed-size StaticBitSet on the
    trace, reset when the selection changes.
  • Bounded for hostile input. Depth ≤ 6, breadth ≤ 40 per container, ≤ 100
    tracked nodes; past them the tree shows a compact ... N more / ... truncated
    marker. The raw view is capped at 8 KiB. Payloads are untrusted (ADR-0007), so
    the inspector can't be made to blow the widget-node budget or the text layout.

Scope note — timeline scroll on jump

Jump-to-first-event selects and highlights the session's first event and
drives the detail/session panels to it. The literal timeline viewport scroll
is not wired: the zero-config UiApp exposes no model-driven scroll control (the
runtime owns the virtual list's offset, keyed by list id), so revealing an
arbitrary row needs the same runner eject as interactive open — tracked under
#33. For realistic traces the first event is already at the top and visible.

Testing

native test -Dplatform=null — 77 headless tests green (macOS local; CI runs
both OSes). New coverage:

  • Payload-tree object/array/scalar shapes, the depth bound (an over-deep chain's
    leaf never renders) and the breadth bound (an over-wide array shows a marker),
    and the total-node bound.
  • Collapse toggling hides a container's descendants through the real on_press
    dispatch.
  • The session panel reflects the event's session; Jump to first event selects
    the session's first event.
  • The accessibility sweep now also covers the enriched detail pane (tree,
    session, raw).

native check --strict clean; native build (ReleaseFast) builds. Living docs
(CURRENT_STATE.md) updated in-branch.

Closes #30

Selecting a timeline row now unpacks the event in the detail pane:

- Normalized fields (id, message id, type, direction, time, error).
- Session panel: the session the event correlates into — transaction id,
  status, connector, start/stop, event count — with a jump-to-first-event
  control that selects and highlights the session's first event.
- Payload tree: a model-owned disclosure tree over the std.json.Value
  (ui.tree + the ARIA keymap). Flat treeitem rows keyed by a collapse-
  independent pre-order id, bounded in depth (6), breadth (40), and total
  node count (100) so a hostile payload can't blow the widget-node budget.
- Raw view: the original OCPP-J array, pretty-printed under a byte cap.

The literal timeline viewport scroll on jump rides the same runner eject as
interactive open (#33); the model-level jump (select + highlight) lands now.

Tests: payload-tree object/array/scalar shapes, the depth and breadth
bounds, collapse toggling, the session panel + jump wiring, and the a11y
sweep over the enriched detail pane.

Closes #30
@sepehr-safari sepehr-safari added type:feature New capability area:ui Native markup views labels Jul 11, 2026
@sepehr-safari sepehr-safari added this to the S3 — Inspector UI milestone Jul 11, 2026
@sepehr-safari
sepehr-safari merged commit 1c6373b into main Jul 11, 2026
3 checks passed
@sepehr-safari
sepehr-safari deleted the feat/message-inspector branch July 11, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ui Native markup views type:feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ui): message inspector + session panel

1 participant